<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.14"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>JSON Voorhees: Serialization Builder DSL</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
  $(document).ready(initResizable);
/* @license-end */</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
</script><script type="text/javascript" async src="http://www.mathjax.org/mathjax/MathJax.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectalign" style="padding-left: 0.5em;">
   <div id="projectname">JSON Voorhees
   </div>
   <div id="projectbrief">Killer JSON for C++</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.14 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function(){initNavTree('serialization_builder_dsl.html','');});
/* @license-end */
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">Serialization Builder DSL </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>Most applications tend to have a lot of structure types.</p>
<p>While it is possible to write an <code>extractor</code> and <code>serializer</code> (or <code>adapter</code>) for each type, this can get a little bit tedious. Beyond that, it is very difficult to look at the contents of adapter code and discover what the JSON might actually look like. The builder DSL is meant to solve these issues by providing a convenient way to describe conversion operations for your C++ types.</p>
<p>At the end of the day, the goal is to take some C++ structures like this:</p>
<div class="fragment"><div class="line"><span class="keyword">struct </span>person</div><div class="line">{</div><div class="line">    std::string first_name;</div><div class="line">    std::string last_name;</div><div class="line">    <span class="keywordtype">int</span>         age;</div><div class="line">    std::string role;</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">struct </span>company</div><div class="line">{</div><div class="line">    std::string         name;</div><div class="line">    <span class="keywordtype">bool</span>                certified;</div><div class="line">    std::vector&lt;person&gt; employees;</div><div class="line">    std::list&lt;person&gt;   candidates;</div><div class="line">};</div></div><!-- fragment --><p>...and easily convert it to an from a JSON representation that looks like this:</p>
<div class="fragment"><div class="line">{</div><div class="line">    <span class="stringliteral">&quot;name&quot;</span>: <span class="stringliteral">&quot;Paul&#39;s Construction&quot;</span>,</div><div class="line">    <span class="stringliteral">&quot;certified&quot;</span>: <span class="keyword">false</span>,</div><div class="line">    <span class="stringliteral">&quot;employees&quot;</span>: [</div><div class="line">        {</div><div class="line">            <span class="stringliteral">&quot;first_name&quot;</span>: <span class="stringliteral">&quot;Bob&quot;</span>,</div><div class="line">            <span class="stringliteral">&quot;last_name&quot;</span>:  <span class="stringliteral">&quot;Builder&quot;</span>,</div><div class="line">            <span class="stringliteral">&quot;age&quot;</span>:        29</div><div class="line">        },</div><div class="line">        {</div><div class="line">            <span class="stringliteral">&quot;first_name&quot;</span>: <span class="stringliteral">&quot;James&quot;</span>,</div><div class="line">            <span class="stringliteral">&quot;last_name&quot;</span>:  <span class="stringliteral">&quot;Johnson&quot;</span>,</div><div class="line">            <span class="stringliteral">&quot;age&quot;</span>:        38,</div><div class="line">            <span class="stringliteral">&quot;role&quot;</span>:       <span class="stringliteral">&quot;Foreman&quot;</span></div><div class="line">        }</div><div class="line">    ],</div><div class="line">    <span class="stringliteral">&quot;candidates&quot;</span>: [</div><div class="line">        {</div><div class="line">            <span class="stringliteral">&quot;firstname&quot;</span>: <span class="stringliteral">&quot;Adam&quot;</span>,</div><div class="line">            <span class="stringliteral">&quot;lastname&quot;</span>:  <span class="stringliteral">&quot;Ant&quot;</span></div><div class="line">        }</div><div class="line">    ]</div><div class="line">}</div></div><!-- fragment --><p>To define a <code>formats</code> for this <code>person</code> type using the serialization builder DSL, you would say:</p>
<div class="fragment"><div class="line"><a class="code" href="classjsonv_1_1formats.html">jsonv::formats</a> fmts =</div><div class="line">    <a class="code" href="classjsonv_1_1formats__builder.html">jsonv::formats_builder</a>()</div><div class="line">        .type&lt;person&gt;()</div><div class="line">            .member(<span class="stringliteral">&quot;first_name&quot;</span>, &amp;person::first_name)</div><div class="line">                .alternate_name(<span class="stringliteral">&quot;firstname&quot;</span>)</div><div class="line">            .member(<span class="stringliteral">&quot;last_name&quot;</span>,  &amp;person::last_name)</div><div class="line">                .alternate_name(<span class="stringliteral">&quot;lastname&quot;</span>)</div><div class="line">            .member(<span class="stringliteral">&quot;age&quot;</span>,        &amp;person::age)</div><div class="line">                .until({ 6,1 })</div><div class="line">                .default_value(21)</div><div class="line">                .default_on_null()</div><div class="line">                .check_input([] (<span class="keywordtype">int</span> value) { <span class="keywordflow">if</span> (value &lt; 0) <span class="keywordflow">throw</span> std::logic_error(<span class="stringliteral">&quot;Age must be positive.&quot;</span>); })</div><div class="line">            .member(<span class="stringliteral">&quot;role&quot;</span>,       &amp;person::role)</div><div class="line">                .since({ 2,0 })</div><div class="line">                .default_value(<span class="stringliteral">&quot;Builder&quot;</span>)</div><div class="line">        .type&lt;company&gt;()</div><div class="line">            .member(<span class="stringliteral">&quot;name&quot;</span>,       &amp;company::name)</div><div class="line">            .member(<span class="stringliteral">&quot;certified&quot;</span>,  &amp;company::certified)</div><div class="line">            .member(<span class="stringliteral">&quot;employees&quot;</span>,  &amp;company::employees)</div><div class="line">            .member(<span class="stringliteral">&quot;candidates&quot;</span>, &amp;company::candidates)</div><div class="line">        .register_containers&lt;company, std::vector, std::list&gt;()</div><div class="line">        .check_references(<a class="code" href="classjsonv_1_1formats.html#ad194791e293229fb6a79438a6444f51b">jsonv::formats::defaults</a>())</div><div class="line">    ;</div></div><!-- fragment --><h1><a class="anchor" id="Reference"></a>
Reference</h1>
<p>The DSL is made up of three major parts:</p>
<ol type="1">
<li><em>formats</em> &ndash; modifies a <code><a class="el" href="classjsonv_1_1formats.html" title="Simply put, this class is a collection of extractor and serializer instances. ">jsonv::formats</a></code> object by adding new type adapters to it</li>
<li><em>type</em> &ndash; modifies the behavior of a <code><a class="el" href="classjsonv_1_1adapter.html" title="An adapter is both an extractor and a serializer. ">jsonv::adapter</a></code> by adding new members to it</li>
<li><em>member</em> &ndash; modifies an individual member inside of a specific type</li>
</ol>
<p>Each successive function call transforms your context. <em>Narrowing</em> calls make your context more specific; for example, calling <code>type</code> from a <em>formats</em> context allows you to modify a specific type. <em>Widening</em> calls make the context less specific and are always available; for example, when in the <em>member</em> context, you can still call <code>type</code> from the <em>formats</em> context to specify a new type.</p>
<div class="dotgraph">
<iframe scrolling="no" frameborder="0" src="dot_inline_dotgraph_1.svg" width="146" height="251"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe></div>
<h2><a class="anchor" id="serialization_builder_dsl_ref_formats"></a>
Formats Context</h2>
<p>Commands in this section modify the behavior of the underlying <code><a class="el" href="classjsonv_1_1formats.html" title="Simply put, this class is a collection of extractor and serializer instances. ">jsonv::formats</a></code> object.</p>
<h3><a class="anchor" id="serialization_builder_dsl_ref_formats_level"></a>
Level</h3>
<h4><a class="anchor" id="serialization_builder_dsl_ref_formats_level_check_references"></a>
check_references</h4>
<ul>
<li><code>check_references(formats)</code></li>
<li><code>check_references(formats, std::string name)</code></li>
<li><code>check_references(formats::list)</code></li>
<li><code>check_references(formats::list, std::string name)</code></li>
<li><code>check_references()</code></li>
<li><code>check_references(std::string name)</code></li>
</ul>
<p>Tests that every type referenced by the members of the output of the DSL have an <code>extractor</code> and a <code>serializer</code>. The provided <code>formats</code> is used to draw extra types from (a common value is <code><a class="el" href="classjsonv_1_1formats.html#ad194791e293229fb6a79438a6444f51b" title="Get the default formats instance. ">jsonv::formats::defaults</a></code>). In other words, it asks the question: If the <code>formats</code> from this DSL was combined with these other <code>formats</code>, could all of the types be encoded and decoded?</p>
<p>This does not mutate the DSL in any way. On successful verification, it will appear that nothing happened. If the verification is not successful, an exception will be thrown with the offending types in the message. For example:</p>
<div class="fragment"><div class="line">There are 2 types referenced that the formats <span class="keywordflow">do</span> not know how to serialize: </div><div class="line"> - date_type (referenced by: name_space::foo, other::name::space::bar)</div><div class="line"> - tree</div></div><!-- fragment --><p>If <em>name</em> is provided, the value will be output to the error message on failure. This can be useful if you have multiple <code>check_references</code> statements and wish to more easily determine the failing <code>formats</code> combination from the error message alone.</p>
<dl class="section note"><dt>Note</dt><dd>This is evaluated <em>immediately</em>, so it is best to call this function as the very last step in the DSL.</dd></dl>
<div class="fragment"><div class="line">.check_references(<a class="code" href="classjsonv_1_1formats.html#ad194791e293229fb6a79438a6444f51b">jsonv::formats::defaults</a>())</div></div><!-- fragment --><h4><a class="anchor" id="serialization_builder_dsl_ref_formats_level_reference_type"></a>
reference_type</h4>
<ul>
<li><code>reference_type(std::type_index type)</code></li>
<li><code>reference_type(std::type_index type, std::type_index from)</code></li>
</ul>
<p>Explicitly add a reference to the provided <em>type</em> in the DSL. If <em>from</em> is provided, also add a back reference for tracking purposes. The <em>from</em> field is useful for tracking <em>why</em> the <em>type</em> is referenced.</p>
<p>Type references are used in <a class="el" href="serialization_builder_dsl.html#serialization_builder_dsl_ref_formats_level_check_references">check_references</a> to both check and generate error messages if the <code>formats</code> the DSL is building cannot fully create and extract JSON values. You do not usually have to call this, as each call to <a class="el" href="serialization_builder_dsl.html#serialization_builder_dsl_ref_type_narrowing_member">member</a> calls this automatically.</p>
<div class="fragment"><div class="line">.reference_type(std::type_index(<span class="keyword">typeid</span>(<span class="keywordtype">int</span>)), std::type_index(<span class="keyword">typeid</span>(my_type)))</div><div class="line">.reference_type(std::type_index(<span class="keyword">typeid</span>(my_type))</div></div><!-- fragment --><h4><a class="anchor" id="serialization_builder_dsl_ref_formats_level_register_adapter"></a>
register_adapter</h4>
<ul>
<li><code>register_adapter(const adapter*)</code></li>
<li><code>register_adapter(std::shared_ptr&lt;const adapter&gt;)</code></li>
</ul>
<p>Register an arbitrary <code>adapter</code> with the <code>formats</code> we are currently building. This is useful for integrating with type adapters that do not (or can not) use the DSL.</p>
<div class="fragment"><div class="line">.register_adapter(my_type::get_adapter())</div></div><!-- fragment --><h4><a class="anchor" id="serialization_builder_dsl_ref_formats_level_register_optional"></a>
register_optional</h4>
<ul>
<li><code>register_optional&lt;TOptional&gt;()</code></li>
</ul>
<p>Similar to <code>register_adapter</code>, but automatically create an <code><a class="el" href="classjsonv_1_1optional__adapter.html" title="An adapter for optional-like types. ">optional_adapter</a>&lt;TOptional&gt;</code> to store.</p>
<div class="fragment"><div class="line">.register_optional&lt;std::optional&lt;int&gt;&gt;()</div><div class="line">.register_optional&lt;boost::optional&lt;double&gt;&gt;()</div></div><!-- fragment --><h4><a class="anchor" id="serialization_builder_dsl_ref_formats_level_register_container"></a>
register_container</h4>
<ul>
<li><code>register_container&lt;TContainer&gt;()</code></li>
</ul>
<p>Similar to <code>register_adapter</code>, but automatically create a <code><a class="el" href="classjsonv_1_1container__adapter.html" title="An adapter for container types. ">container_adapter</a>&lt;TContainer&gt;</code> to store.</p>
<div class="fragment"><div class="line">.register_container&lt;std::vector&lt;int&gt;&gt;()</div><div class="line">.register_container&lt;std::list&lt;std::string&gt;&gt;()</div></div><!-- fragment --><h4><a class="anchor" id="serialization_builder_dsl_ref_formats_level_register_containers"></a>
register_containers</h4>
<ul>
<li><code>register_containers&lt;T, template &lt;T, ...&gt;... TTContainer&gt;</code></li>
</ul>
<p>Convenience function for calling <code>register_container</code> for multiple containers with the same <code>value_type</code>. Unfortunately, it only supports varying the first template parameter of the <code>TTContainer</code> types, so if you wish to do something like vary the allocator, you will have to either call <code>register_container</code> multiple times or use a template alias.</p>
<div class="fragment"><div class="line">.register_containers&lt;int, std::list, std::deque&gt;()</div><div class="line">.register_containers&lt;double, std::vector, std::set&gt;()</div></div><!-- fragment --><dl class="section note"><dt>Note</dt><dd>Not supported in MSVC 14 (CTP 5).</dd></dl>
<h4><a class="anchor" id="serialization_builder_dsl_ref_formats_level_register_wrapper"></a>
register_wrapper</h4>
<ul>
<li><code>register_wrapper&lt;TWrapper&gt;()</code></li>
</ul>
<p>Similar to <code>register_adapter</code>, but automatically create an <code><a class="el" href="classjsonv_1_1wrapper__adapter.html" title="An adapter for &quot;wrapper&quot; types. ">wrapper_adapter</a>&lt;TWrapper&gt;</code> to store.</p>
<div class="fragment"><div class="line">.register_optional&lt;std::optional&lt;int&gt;&gt;()</div><div class="line">.register_optional&lt;boost::optional&lt;double&gt;&gt;()</div></div><!-- fragment --><h4><a class="anchor" id="serialization_builder_dsl_ref_formats_level_enum_type"></a>
enum_type</h4>
<ul>
<li><code>enum_type&lt;TEnum&gt;(std::string name, std::initializer_list&lt;std::pair&lt;TEnum, <a class="el" href="classjsonv_1_1value.html" title="Represents a single JSON value, which can be any one of a potential kind, each behaving slightly diff...">jsonv::value</a>&gt;&gt;)</code></li>
<li><code>enum_type_icase&lt;TEnum&gt;(std::string name, std::initializer_list&lt;std::pair&lt;TEnum, <a class="el" href="classjsonv_1_1value.html" title="Represents a single JSON value, which can be any one of a potential kind, each behaving slightly diff...">jsonv::value</a>&gt;&gt;)</code></li>
</ul>
<p>Create an adapter for the <code>TEnum</code> type with a mapping of C++ values to JSON values and vice versa. The most common use of this is to map <code>enum</code> values in C++ to string representations in JSON. <code>TEnum</code> is not restricted to types which are <code>enum</code>, but can be anything which you would like to restrict to a limited subset of possible values. Likewise, JSON representations are not restricted to being of <code>kind::string</code>.</p>
<p>The sibling function <code>enum_type_icase</code> will create an adapter which uses case-insensitive checking when converting to C++ values in <code>extract</code>.</p>
<div class="fragment"><div class="line">.enum_type&lt;ring&gt;(<span class="stringliteral">&quot;ring&quot;</span>,</div><div class="line">                 {</div><div class="line">                   { ring::fire,  <span class="stringliteral">&quot;fire&quot;</span>    },</div><div class="line">                   { ring::wind,  <span class="stringliteral">&quot;wind&quot;</span>    },</div><div class="line">                   { ring::earth, <span class="stringliteral">&quot;earth&quot;</span>   },</div><div class="line">                   { ring::water, <span class="stringliteral">&quot;water&quot;</span>   },</div><div class="line">                   { ring::heart, <span class="stringliteral">&quot;heart&quot;</span>   }, <span class="comment">// &quot;heart&quot; is preferred for to_json</span></div><div class="line">                   { ring::heart, <span class="stringliteral">&quot;useless&quot;</span> }, <span class="comment">// &quot;useless&quot; is interpreted as ring::heart in extract</span></div><div class="line">                   { ring::fire,  1         }, <span class="comment">// the JSON value 1 will also be interpreted as ring::fire in extract</span></div><div class="line">                   { ring::ussr,  <span class="stringliteral">&quot;wind&quot;</span>    }, <span class="comment">// old C++ value ring::ussr will get output as &quot;wind&quot;</span></div><div class="line">                 }</div><div class="line">                )</div><div class="line">.enum_type_icase&lt;int&gt;(<span class="stringliteral">&quot;integer&quot;</span>,</div><div class="line">                      {</div><div class="line">                        { 0, <span class="stringliteral">&quot;zero&quot;</span>   },</div><div class="line">                        { 0, <span class="stringliteral">&quot;naught&quot;</span> },</div><div class="line">                        { 1, <span class="stringliteral">&quot;one&quot;</span>    },</div><div class="line">                        { 2, <span class="stringliteral">&quot;two&quot;</span>    },</div><div class="line">                        { 3, <span class="stringliteral">&quot;three&quot;</span>  },</div><div class="line">                      }</div><div class="line">                     )</div></div><!-- fragment --><dl class="section see"><dt>See also</dt><dd><a class="el" href="classjsonv_1_1enum__adapter.html" title="An adapter for enumeration types. ">enum_adapter</a></dd></dl>
<h4><a class="anchor" id="serialization_builder_dls_ref_formats_level_polymorphic_type"></a>
polymorphic_type</h4>
<ul>
<li><code>polymorphic_type&lt;&lt;TPointer&gt;(std::string discrimination_key);</code></li>
</ul>
<p>Create an adapter for the <code>TPointer</code> type (usually <code>std::shared_ptr</code> or <code>std::unique_ptr</code>) that knows how to serialize and deserialize one or more types that can be polymorphically represented by <code>TPointer</code>, i.e. derived types. It uses a discrimination key to determine which concrete type should be instantiated when extracting values from json.</p>
<div class="fragment"><div class="line">.polymorphic_type&lt;std::unique_ptr&lt;base&gt;&gt;(<span class="stringliteral">&quot;type&quot;</span>)</div><div class="line">  .subtype&lt;derived_1&gt;(<span class="stringliteral">&quot;derived_1&quot;</span>)</div><div class="line">  .subtype&lt;derived_2&gt;(<span class="stringliteral">&quot;derived_2&quot;</span>, <a class="code" href="group__Serialization.html#ggaaee4cddaeb99aafe88212663f93b9856a0ba4439ee9a46d9d9f14c60f88f45f87">keyed_subtype_action::check</a>)</div><div class="line">  .subtype&lt;derived_3&gt;(<span class="stringliteral">&quot;derived_3&quot;</span>, <a class="code" href="group__Serialization.html#ggaaee4cddaeb99aafe88212663f93b9856ae0df5f3dfd2650ae5be9993434e2b2c0">keyed_subtype_action::insert</a>);</div></div><!-- fragment --><p>The keyed_subtype_action can be used to configure the adapter to make sure that the discrimination key was correctly serialized (<a class="el" href="group__Serialization.html#ggaaee4cddaeb99aafe88212663f93b9856a0ba4439ee9a46d9d9f14c60f88f45f87">keyed_subtype_action::check</a>) or to insert the discrimination key for the underlying type so that the underlying type doesn't need to do that itself (<a class="el" href="group__Serialization.html#ggaaee4cddaeb99aafe88212663f93b9856ae0df5f3dfd2650ae5be9993434e2b2c0">keyed_subtype_action::insert</a>). The default is to do nothing (<a class="el" href="group__Serialization.html#ggaaee4cddaeb99aafe88212663f93b9856a334c4a4c42fdb79d7ebc3e73b517e6f8">keyed_subtype_action::none</a>).</p>
<h4><a class="anchor" id="serialization_builder_dsl_ref_formats_level_extend"></a>
extend</h4>
<ul>
<li><code>extend(std::function&lt;void (<a class="el" href="classjsonv_1_1formats__builder.html">formats_builder</a>&amp;)&gt; func)</code></li>
</ul>
<p>Extend the <code><a class="el" href="classjsonv_1_1formats__builder.html">formats_builder</a></code> with the provided <em>func</em> by passing the current builder to it. This provides a more convenient way to call helper functions.</p>
<div class="fragment"><div class="line"><a class="code" href="classjsonv_1_1formats__builder.html">jsonv::formats_builder</a> builder;</div><div class="line">foo(builder);</div><div class="line">bar(builder);</div><div class="line">baz(builder);</div></div><!-- fragment --><p>This can be done equivalently with: </p><div class="fragment"><div class="line"><a class="code" href="classjsonv_1_1formats__builder.html">jsonv::formats_builder</a>()</div><div class="line">  .extend(foo)</div><div class="line">  .extend(bar)</div><div class="line">  .extend(baz)</div></div><!-- fragment --><h4><a class="anchor" id="serialization_builder_dsl_ref_formats_level_on_duplicate_type"></a>
on_duplicate_type</h4>
<ul>
<li><code>on_duplicate_type(on_duplicate_type_action action);</code></li>
</ul>
<p>Set what action to take when attempting to register an adapter, but there is already an adapter for that type in the formats. The default is to throw a <a class="el" href="classjsonv_1_1duplicate__type__error.html">duplicate_type_error</a> exception (<a class="el" href="group__Serialization.html#gga645b8b2ddf86926dab927adb704ea352a42552b1f133f9f8eb406d4f306ea9fd1">duplicate_type_action::exception</a>), but the <code><a class="el" href="classjsonv_1_1formats__builder.html">formats_builder</a></code> can also be configured to ignore the duplicate (<a class="el" href="group__Serialization.html#gga645b8b2ddf86926dab927adb704ea352a567bc1d268f135496de3d5b946b691f3">duplicate_type_action::ignore</a>), or to replace the existing adapter with the new one (<a class="el" href="group__Serialization.html#gga645b8b2ddf86926dab927adb704ea352a9dde360102c103867bd2f45872f1129c">duplicate_type_action::replace</a>). This is useful when calling multiple <code>extend</code> methods that may add common types to the <code><a class="el" href="classjsonv_1_1formats__builder.html">formats_builder</a></code>.</p>
<h3><a class="anchor" id="serialization_builder_dsl_ref_formats_narrowing"></a>
Narrowing</h3>
<h4><a class="anchor" id="serialization_builder_dsl_ref_formats_narrowing_type"></a>
type&lt;T&gt;</h4>
<ul>
<li><code>type&lt;T&gt;()</code></li>
<li><code>type&lt;T&gt;(std::function&lt;void (<a class="el" href="classjsonv_1_1adapter__builder.html">adapter_builder</a>&lt;T&gt;&amp;)&gt; func)</code></li>
</ul>
<p>Create an <code>adapter</code> for type <code>T</code> and begin building the members for it. If <em>func</em> is provided, it will be called with the <a class="el" href="classjsonv_1_1adapter__builder.html">adapter_builder</a>&lt;T&gt; this call to <code>type</code> creates, which can be used for creating common extension functions.</p>
<div class="fragment"><div class="line">.type&lt;my_type&gt;()</div><div class="line">    .member(...)</div><div class="line">    .</div><div class="line">    .</div><div class="line">    .</div></div><!-- fragment --><h2><a class="anchor" id="serialization_builder_dsl_ref_type"></a>
Type Context</h2>
<p>Commands in this section modify the behavior of the <code><a class="el" href="classjsonv_1_1adapter.html" title="An adapter is both an extractor and a serializer. ">jsonv::adapter</a></code> for a particular type.</p>
<h3><a class="anchor" id="serialization_builder_dsl_ref_type_level"></a>
Level</h3>
<h4><a class="anchor" id="serialization_builder_dsl_ref_type_level_pre_extract"></a>
pre_extract</h4>
<ul>
<li><code>pre_extract(std::function&lt;void (const <a class="el" href="classjsonv_1_1extraction__context.html">extraction_context</a>&amp; context, const value&amp; from)&gt; perform)</code></li>
</ul>
<p>Call the given <em>perform</em> function during the <code>extract</code> operation, but before performing any extraction. This can be called multiple times &ndash; all functions will be called in the order they are provided.</p>
<h4><a class="anchor" id="serialization_builder_dsl_ref_type_level_default_on_null"></a>
type_default_on_null</h4>
<ul>
<li><code>type_default_on_null()</code></li>
<li><code>type_default_on_null(bool on)</code></li>
</ul>
<p>If the JSON value <code>null</code> is in the input, should this type take on some default? This should be used with <a class="el" href="serialization_builder_dsl.html#serialization_builder_dsl_ref_type_level_type_default_value">serialization_builder_dsl_ref_type_level_type_default_value</a> type_default_value.</p>
<h4><a class="anchor" id="serialization_builder_dsl_ref_type_level_type_default_value"></a>
serialization_builder_dsl_ref_type_level_type_default_value</h4>
<ul>
<li><code>type_default_value(T value)</code></li>
<li><code>type_default_value(std::function&lt;T (const <a class="el" href="classjsonv_1_1extraction__context.html">extraction_context</a>&amp; context)&gt;)</code></li>
</ul>
<p>What value should be used to create the default for this type?</p>
<div class="fragment"><div class="line">.type&lt;my_type&gt;()</div><div class="line">    .type_default_on_null()</div><div class="line">    .type_default_value(my_type(<span class="stringliteral">&quot;default&quot;</span>))</div></div><!-- fragment --><h4><a class="anchor" id="serialization_builder_dsl_ref_type_level_on_extract_extra_keys"></a>
on_extract_extra_keys</h4>
<ul>
<li><code>on_extract_extra_keys(std::function&lt;void (const <a class="el" href="classjsonv_1_1extraction__context.html">extraction_context</a>&amp; context, const value&amp; from, std::set&lt;std::string&gt; extra_keys)&gt; action )</code></li>
</ul>
<p>When extracting, perform some <em>action</em> if extra keys are provided. By default, extra keys are usually simply ignored, so this is useful if you wish to throw an exception (or anything you want).</p>
<div class="fragment"><div class="line">.type&lt;my_type&gt;()</div><div class="line">    .member(<span class="stringliteral">&quot;x&quot;</span>, &amp;my_type::x)</div><div class="line">    .member(<span class="stringliteral">&quot;y&quot;</span>, &amp;my_type::y)</div><div class="line">    .on_extract_extra_keys([] (<span class="keyword">const</span> extraction_context&amp;, <span class="keyword">const</span> value&amp;, std::set&lt;std::string&gt; extra_keys)</div><div class="line">                           {</div><div class="line">                               <span class="keywordflow">throw</span> extracted_extra_keys(<span class="stringliteral">&quot;my_type&quot;</span>, std::move(extra_keys));</div><div class="line">                           }</div><div class="line">                          )</div></div><!-- fragment --><p>There is a convenience function named <code>throw_extra_keys_extraction_error</code> which does this for you.</p>
<div class="fragment"><div class="line">.type&lt;my_type&gt;()</div><div class="line">    .member(<span class="stringliteral">&quot;x&quot;</span>, &amp;my_type::x)</div><div class="line">    .member(<span class="stringliteral">&quot;y&quot;</span>, &amp;my_type::y)</div><div class="line">    .on_extract_extra_keys(jsonv::throw_extra_keys_extraction_error)</div></div><!-- fragment --><h3><a class="anchor" id="serialization_builder_dsl_ref_type_narrowing"></a>
Narrowing</h3>
<h4><a class="anchor" id="serialization_builder_dsl_ref_type_narrowing_member"></a>
member</h4>
<ul>
<li><code>member(std::string name, TMember T::*selector)</code></li>
<li><code>member(std::string name, const TMember&amp; (*access)(const T&amp;), void (*mutate)(T&amp;, TMember&amp;&amp;))</code></li>
<li><code>member(std::string name, const TMember&amp; (T::*access)() const, TMember&amp; (T::*mutable_access)())</code></li>
<li><code>member(std::string name, const TMember&amp; (T::*access)() const, void (T::*mutate)(TMember))</code></li>
<li><code>member(std::string name, const TMember&amp; (T::*access)() const, void (T::*mutate)(TMember&amp;&amp;))</code></li>
</ul>
<p>Adds a member to the type we are currently building. By default, the member will be serialized with the key of the given <em>name</em> and the extractor will search for the given <em>name</em>. If you wish to change properties of this field, use the <a class="el" href="serialization_builder_dsl.html#serialization_builder_dsl_ref_member">Member Context</a>.</p>
<div class="fragment"><div class="line">.type&lt;my_type&gt;()</div><div class="line">    .member(<span class="stringliteral">&quot;x&quot;</span>, &amp;my_type::x)</div><div class="line">    .member(<span class="stringliteral">&quot;y&quot;</span>, &amp;my_type::y)</div><div class="line">    .member(<span class="stringliteral">&quot;thing&quot;</span>, &amp;my_type::get_thing, &amp;my_type::set_thing)</div></div><!-- fragment --><h2><a class="anchor" id="serialization_builder_dsl_ref_member"></a>
Member Context</h2>
<p>Commands in this section modify the behavior of a particular member. Here, <code>T</code> refers to the containing type (the one we are adding a member to) and <code>TMember</code> refers to the type of the member we are modifying.</p>
<h3><a class="anchor" id="serialization_builder_dsl_ref_member_level"></a>
Level</h3>
<h4><a class="anchor" id="serialization_builder_dsl_ref_member_level_after"></a>
after</h4>
<ul>
<li><code>after(version)</code></li>
</ul>
<p>Only serialize this member if the <code><a class="el" href="classjsonv_1_1context__base.html#a5adeb5450d5c481ad57518325cd39243" title="Get the version this extraction_context was created with. ">serialization_context::version</a></code> is not <code><a class="el" href="structjsonv_1_1version.html#a5d00ab0d764ee411312abf8fe2cc0963" title="Check if this version is an &quot;empty&quot; value – meaning major and minor are both 0. ">version::empty</a></code> and is greater than or equal to the provided <code>version</code>.</p>
<h4><a class="anchor" id="serialization_builder_dsl_ref_member_level_alternate_name"></a>
alternate_name</h4>
<ul>
<li><code>alternate_name(std::string name)</code></li>
</ul>
<p>Provide an alternate name to search for when extracting this member. If a user provides values for multiple names, preference is given to names earlier in the list, starting with the original given name.</p>
<h4><a class="anchor" id="serialization_builder_dsl_ref_member_level_before"></a>
before</h4>
<ul>
<li><code>before(version)</code></li>
</ul>
<p>Only serialize this member if the <code><a class="el" href="classjsonv_1_1context__base.html#a5adeb5450d5c481ad57518325cd39243" title="Get the version this extraction_context was created with. ">serialization_context::version</a></code> is not <code><a class="el" href="structjsonv_1_1version.html#a5d00ab0d764ee411312abf8fe2cc0963" title="Check if this version is an &quot;empty&quot; value – meaning major and minor are both 0. ">version::empty</a></code> and is less than or equal to the provided <code>version</code>.</p>
<h4><a class="anchor" id="serialization_builder_dsl_ref_member_level_check_input"></a>
check_input</h4>
<ul>
<li><code>check_input(std::function&lt;void (const TMember&amp;)&gt; check)</code></li>
<li><code>check_input(std::function&lt;bool (const TMember&amp;)&gt; check, std::function&lt;void (const TMember&amp;)&gt; thrower)</code></li>
<li><code>check_input(std::function&lt;bool (const TMember&amp;)&gt; check, TException ex)</code></li>
</ul>
<p>Checks the extracted value with the given <em>check</em> function. In the first form, you are expected to throw inside the function. In the latter forms, the second parameter will be invoked (in the case of <em>thrower</em>) or thrown directly (in the case of <em>ex</em>).</p>
<div class="fragment"><div class="line">.member(<span class="stringliteral">&quot;x&quot;</span>, &amp;my_type::x)</div><div class="line">    .check_input([] (<span class="keywordtype">int</span> x) { <span class="keywordflow">if</span> (x &lt; 0) <span class="keywordflow">throw</span> std::logic_error(<span class="stringliteral">&quot;x must be greater than 0&quot;</span>); })</div><div class="line">    .check_input([] (<span class="keywordtype">int</span> x) { <span class="keywordflow">return</span> x &lt; 100; }, [] (<span class="keywordtype">int</span> x) { <span class="keywordflow">throw</span> exceptions::less_than(100, x); })</div><div class="line">    .check_input([] (<span class="keywordtype">int</span> x) { <span class="keywordflow">return</span> x % 2 == 0; }, std::logic_error(<span class="stringliteral">&quot;x must be divisible by 2&quot;</span>))</div></div><!-- fragment --><h4><a class="anchor" id="serialization_builder_dsl_ref_member_level_default_value"></a>
default_value</h4>
<ul>
<li><code>default_value(TMember value)</code></li>
<li><code>default_value(std::function&lt;TMember (const <a class="el" href="classjsonv_1_1extraction__context.html">extraction_context</a>&amp;, const value&amp;)&gt; create)</code></li>
</ul>
<p>Provide a default value for this member if no key is found when extracting. You can use the function implementation to synthesize the key however you want.</p>
<div class="fragment"><div class="line">.member(<span class="stringliteral">&quot;x&quot;</span>, &amp;my_type::x)</div><div class="line">    .default_value(10)</div></div><!-- fragment --><h4><a class="anchor" id="serialization_builder_dsl_ref_member_level_default_on_null"></a>
default_on_null</h4>
<ul>
<li><code>default_on_null()</code></li>
<li><code>default_on_null(bool on)</code></li>
</ul>
<p>If the value associated with this key is <code>kind::null</code>, should that be treated as the default value? This option is only considered if a <a class="el" href="serialization_builder_dsl.html#serialization_builder_dsl_ref_member_level_default_value">default_value</a> default_value was provided.</p>
<h4><a class="anchor" id="serialization_builder_dsl_ref_member_level_encode_if"></a>
encode_if</h4>
<ul>
<li><code>encode_if(std::function&lt;bool (const <a class="el" href="classjsonv_1_1serialization__context.html">serialization_context</a>&amp;, const TMember&amp;)&gt; check)</code></li>
</ul>
<p>Only serialize this member if the <em>check</em> function returns true.</p>
<h4><a class="anchor" id="serialization_builder_dsl_ref_member_level_since"></a>
since</h4>
<ul>
<li><code>since(version)</code></li>
</ul>
<p>Only serialize this member if the <code><a class="el" href="classjsonv_1_1context__base.html#a5adeb5450d5c481ad57518325cd39243" title="Get the version this extraction_context was created with. ">serialization_context::version</a></code> is not <code><a class="el" href="structjsonv_1_1version.html#a5d00ab0d764ee411312abf8fe2cc0963" title="Check if this version is an &quot;empty&quot; value – meaning major and minor are both 0. ">version::empty</a></code> and is greater than the provided <code>version</code>.</p>
<h4><a class="anchor" id="serialization_builder_dsl_ref_member_level_until"></a>
until</h4>
<ul>
<li><code>until(version)</code></li>
</ul>
<p>Only serialize this member if the <code><a class="el" href="classjsonv_1_1context__base.html#a5adeb5450d5c481ad57518325cd39243" title="Get the version this extraction_context was created with. ">serialization_context::version</a></code> is not <code><a class="el" href="structjsonv_1_1version.html#a5d00ab0d764ee411312abf8fe2cc0963" title="Check if this version is an &quot;empty&quot; value – meaning major and minor are both 0. ">version::empty</a></code> and is less than the provided <code>version</code>. </p>
</div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  <ul>
    <li class="footer">Generated by
    <a href="http://www.doxygen.org/index.html">
    <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.14 </li>
  </ul>
</div>
</body>
</html>
